Repository navigation
feat(protocol)!: adopt the signed AdCP 3.3.0-beta.6 bundle - #1901
Conversation
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean adoption of the signed AdCP 3.3.0-beta.6 schema bundle.
What I checked:
high_risk: trueis driven entirely by(added)files underschemas/**(the 3.3.0-beta.6 cache bundle). New files matching a high-risk glob are normal scaffolding/codegen for a schema bump and are not escalation-worthy on the flag alone — nothing existed to break.gated_paths: false, so the deterministic hard approval gate (row 2) does not apply.- No no-auto-approve team match (row 7 N/A).
- Semver signal is correct: commit carries
feat(protocol)!:+BREAKING CHANGE:footer with migration notes for the beta.5→beta.6 swap. - The five hand-written SDK fixes for now-open schemas are fail-closed (reporting scope, receipt-history arms, inspection revalidation, proposal webhook key rejection).
- Origin-only agent matching is sound (scheme/trailing-slash normalization, prefix-attack boundary, consistent
path == "/"handling). _forward_compat/_ergonomicchanges and packaging bumps are consistent and tested;domains/churn is expected codegen.
Reviewer surfaced no Critical/High/Medium findings. No escalation trigger (no deletions, no medium on a modified sensitive file, no prior escalate). Falls through to row 9.
Pin src/adcp/ADCP_VERSION to 3.3.0-beta.6 from the audited, cosign-verified release: schemas/releases/3.3.0-beta.6.json, source commit aa94f361d7cd from the Fulcio certificate (the tag is its Version Packages child), bundle sha256 99c0ba47f42c. Resync the schema cache, packaged compliance inputs and request-signing vectors through the audited pin, regenerate the types from the beta.5 tree and the public API snapshot. The wheel ships the beta.6 schemas and compliance tree; the beta.5 trees stay in the repository as history. Withdrawals (adcp#8501): the 3.3 additions to the deprecated get_products, create_media_buy / update_media_buy and the sync_creatives assignments[] row leave the generated types, among them price_adjustments, execution_readiness on get_products (moved to list_products), include_collections, lineage_reason, predecessor_media_buy_id, target_audiences, counting_mechanisms and start_requires_all_creatives_approved off every package but PackageControl. The control_media_buy start-policy gate stays; the dead PackageForecastInput forward-compat bridge is removed. Schemas open within a major (DR-0036), so three checks no longer lean on a closed schema: a reporting delivery scope keeps an unknown selector as received and never widens it to all_media_buys; prepare_proposal_created refuses undeclared keys, since proposal.created stays identifiers-only; and receipt history accepts only the keys the store writes. Spec rules applied in hand-written code: an origin-only authorized_agents[].url authorizes every agent at that origin (adcp#8862), in find_authorized_agent_entries and fetch_publisher_signing_pins, where an exact URL entry still wins; adcp.negotiation treats installment_changes as a typed, capability-gated revision and its unsatisfied entries under the constraint_unsatisfiable rules (adcp#8967); the reporting manifest inspector validates a report definition against the pinned schema, so the 1.1 official_correction_mode and 1.2 package_id rules apply (adcp#8971), and the spec's report-definition vectors run through the SDK's validator. The post-generate reporting scope fixer keeps an unknown selector and refuses a second key, mirroring maxProperties: 1. BREAKING CHANGE: the SDK no longer advertises or accepts AdCP 3.3-beta.5. get_supported_adcp_versions is 3.0, 3.1, 3.2, 3.3-beta.6 and 3.2-rc.7; an adcp_version pin of 3.3-beta.5 or 3.3.0-beta.5 raises ConfigurationError, and a peer that advertises only 3.3-beta.5 for the 3.3 line negotiates down to 3.2. Re-pin to 3.3-beta.6 or omit the pin. Generated types withdrawn by adcp#8501 are gone (PriceAdjustments, PriceAdjustmentsMismatchDetails, PackageForecastInput, AudienceEvidenceTarget and the fields above), most generated models now keep unknown keys instead of refusing them, and a 1.1 or 1.2 report definition that breaks its schema conditionals now fails manifest inspection with INVALID_CONTRACT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
00e7a88 to
f6f78f0
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — AdCP 3.3.0-beta.6 bundle adoption.
No blocking findings. Clean reviewer pass with zero critical/high/medium findings.
Decision table walk-through:
- Row 1 (critical/high): no findings — skip.
- Row 2 (gated_paths + not APPROVED): gated_paths is false — skip. (Also review_decision is APPROVED.)
- Row 3 (high_risk + deleted): high_risk is true, but all high_risk_reasons entries are
(added)— new schema cache files, normal regeneration scaffolding. No(deleted)entry — skip. - Row 4 (medium + data-loss/schema/infra): no findings — skip.
- Row 5 (high_risk modified + medium): all entries are
(added), no(modified), no medium findings — skip. - Row 6 (sticky escalate): prior decision was
approve, notescalate— skip. - Row 7 (no-auto-approve team): no team match — skip.
- Row 8 (3+ medium): zero medium findings — skip.
- Row 9: approve.
The high_risk flag fires solely on added schema cache files matching schemas/** — inherently low risk per the change-kind guidance (nothing existed to break). The reviewer confirmed the diff is overwhelmingly regeneration churn paired with the ADCP_VERSION bump, with hand-written changes being deliberate, spec-cited, and test-covered: origin-only authorization is fail-closed, installment_changes verification has new tests, wire.py exact-key tightening and reporting-scope fail-closed improvements are sound, and breaking removals carry the feat(protocol)! marker plus MIGRATION_v9_to_v10.md satisfying the semver-signal gate. No V1 contamination, no credential-in-metadata issue, no CI-gate disabling, no forward-compat union regressions.
Adopts the signed AdCP
3.3.0-beta.6bundle on the SDK 10 /nextline, following #1866. It ships as 10.0.0b17; 10.0.0b16 went out with the3.3.0-beta.5pin.Pin
schemas/releases/3.3.0-beta.6.jsonrecords:aa94f361d7cd, taken from the Fulcio certificate. Thev3.3.0-beta.6tag (bf4aa6db) is its "Version Packages" child.99c0ba47f42c…, 27,719,655 bytes, plus the.sig,.crtand.sha256sidecars.cosign verify-blobagainstrelease.yml@refs/heads/mainprintsVerified OK.make regenerate-schemastook the audited-pin path: checksum and signing identity verified, no fallback.SCHEMA_DELTAS.mdis the full beta.5 → beta.6 delta._compliancetree. The beta.5 trees stay in the repo as history and are pruned from distributions.What beta.6 changes, and what the SDK does
get_products,create_media_buy/update_media_buyand thesync_creativesassignments[]rowprice_adjustments(PriceAdjustments,PriceAdjustmentsMismatchDetails),include_collections/collections/execution_readinessonget_products(execution readiness moves tolist_products),lineage_reason,predecessor_media_buy_id,target_audiences,counting_mechanisms,PackageForecastInput, andstart_requires_all_creatives_approvedon every package exceptPackageControl. Thecontrol_media_buystart-policy gate (#1872/#1878) stays, because beta.6 keeps the field there. The deadPackageForecastInputforward-compat bridge is removed.authorized_agents[].url(adcp#8862)find_authorized_agent_entries, and every adagents verifier that uses it, now lets an entry with root path and no query authorize any agent at that origin. An entry with a path still matches exactly.fetch_publisher_signing_pinsapplies the same rule, but an exact URL entry still wins.adcp.negotiationnow:• treats
installment_changesas a typed revision;• gates it on
supported_dimensions;• applies the
constraint_unsatisfiablerules tounsatisfied_installment_changes;• checks each unsatisfied entry repeats a requested change.
remove_media_buy_frequency_cap(pre-existing) also counts as a typed revision now.contract_version1.2 (adcp#8971)official_correction_moderule and the 1.2package_idrule apply. The generated model omits both. The spec's report-definition vectors run through the SDK's validator.compute_terms_digesthashes the raw wire mapping.supported_delivery_types,supports_registry_policy_enforcement, geo labels,card_image_sizes, video containers,UNRECOGNIZED_TERMSSDK fixes for opened schemas
scope. The post-generate fixer turned any scope without a known selector intoall_media_buys: true. With the scope open, a future{"x": ...}selector would have been widened to every buy. It now keeps an unknown selector as received, refuses a second key (maxProperties: 1), and expands only an empty scope.proposal.created. Its schema is open, but its text still says "identifiers only… cannot inject terms or instructions".WebhookSender.prepare_proposal_creatednow refuses undeclared keys itself.RECEIPT_HISTORY_CORRUPT.sync_principalis now graded by schema parity. Tests that usedget_productsas a 3.3-only example now uselist_products, because beta.6 keepsget_productsat its 3.2 shape.Reporting vectors and storage contract
SPEC_COMMITis unchanged. All 138 vectors, 8 offering checks and 3 differential regressions pass.REPORTING_STORAGE_CONTRACT == STORAGE_CONTRACT == 2, and no ledger column changes.Not done
extend_hold, which predates beta.5: preflight still refuses it, and the finalize checks would fail a successful one.Breaking
3.3-beta.6and no longer accepts3.3-beta.5.get_supported_adcp_versions()returns3.0, 3.1, 3.2, 3.3-beta.6, 3.2-rc.7. There is no alias, per the one-beta rule.All of this is recorded in
MIGRATION_v9_to_v10.mdand indocs/adcp-3.3-sdk-inventory.mdsection 16.Verification
Local, on
f6f78f094:make validate-generated: pass.make lint: pass. The pre-commit ruff, mypy and adopter type-check hooks pass.5f891597): 21,990 passed. The only failures were release identity and snapshot values, now filled in, andpython -m buildtimeouts caused by load on this host (average about 160).python -m buildtimeout caused by host load (CI runs packaging separately). The one failure wastest_targeting_overlay_schema's list of bare advertised fields, which now includes beta.6'sgeo_value_labels: the generator emits that inline object as its own class, likeage_restriction. The fix is folded intof6f78f094.make typecheck-all: mypy, adopter mypy-strict, pyright and the type-ignore contract all pass.00e7a88ef): everything passed except the Python matrix, which failed only on that targeting test. That includes Postgres conformance, installed production reporting and the frozen feed.blackandbanditwere skipped for this commit, as for feat(protocol)!: adopt the signed AdCP 3.3.0-beta.5 bundle #1866. Both flag only code that was already that way onnext, and CI runs neither.BREAKING CHANGE: the SDK no longer advertises or accepts AdCP 3.3-beta.5. get_supported_adcp_versions is 3.0, 3.1, 3.2, 3.3-beta.6 and 3.2-rc.7; an adcp_version pin of 3.3-beta.5 or 3.3.0-beta.5 raises ConfigurationError, and a peer that advertises only 3.3-beta.5 for the 3.3 line negotiates down to 3.2. Re-pin to 3.3-beta.6 or omit the pin. Generated types withdrawn by adcp#8501 are gone, most generated models now keep unknown keys instead of refusing them, and a 1.1 or 1.2 report definition that breaks its schema conditionals now fails manifest inspection with INVALID_CONTRACT.
🤖 Generated with Claude Code